package com.shadow.demo.info.service;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shadow.demo.common.constants.PunctuationConstants;
import com.shadow.demo.common.enums.shiro.RCodeEnum;
import com.shadow.demo.common.form.SitePublicForm;
import com.shadow.demo.common.info.IPTypeEnum;
import com.shadow.demo.common.info.SitePrefixEnum;
import com.shadow.demo.data.bo.LoginUser;
import com.shadow.demo.data.bo.Query;
import com.shadow.demo.data.info.entity.IpInfoEntity;
import com.shadow.demo.data.info.entity.SiteInfoEntity;
import com.shadow.demo.data.info.mapper.SiteInfoMapper;
import com.shadow.demo.common.info.SiteEnum;
import com.shadow.demo.shiro.util.UserUtils;
import com.shadow.demo.info.config.SiteConfig;
import com.shadow.demo.info.excel.Site35Listener;
import com.shadow.demo.excel.easy.excel.EasyExcelUtil;
import com.shadow.demo.info.excel.SiteVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@AllArgsConstructor
@DS("info")
@Service
public class SiteService extends ServiceImpl<SiteInfoMapper, SiteInfoEntity> {

    private final SiteInfoMapper siteMapper;
    private final IpInfoService ipInfoService;

    /**
     * 获取所有的类型
     * */
    public Set<String> getTypeByRole(final Collection<String> roleCodes) {
        log.info("getTypeByRole roleCode:{}", roleCodes);
        return siteMapper.getTypeByRole(roleCodes);
    }

    /**
     * 获取网址列表
     *
     * @param form 查询表单
     */
    public List<SiteInfoEntity> getPublicList(final SitePublicForm form) {
        if (form == null) {
            return Collections.emptyList();
        }
        // 默认公共域
        if (CollectionUtils.isEmpty(form.getPart())) {
            form.getPart().add(SiteConfig.PUBLIC_PART);
        }
        List<String> codeList = Arrays.asList(RCodeEnum.S.getCode(), RCodeEnum.A.getCode(), RCodeEnum.SITE_A.getCode());
        boolean isSiteAdmin = !Objects.isNull(form.getRoles())
                && CollectionUtils.containsAny(form.getRoles(), codeList);
        // 删除权限, 类型, 域 .in(SiteInfoEntity::getPart, form.getPart())
        final LambdaQueryWrapper<SiteInfoEntity> wrapper = new LambdaQueryWrapper<SiteInfoEntity>()
                .eq(!isSiteAdmin, SiteInfoEntity::getIsPublic, Boolean.TRUE)
                .eq(SiteInfoEntity::getStatus, SiteEnum.NOR.getStatus())
                .eq(StringUtils.isNotEmpty(form.getType()), SiteInfoEntity::getType, form.getType())
                .orderByDesc(SiteInfoEntity::getTitle);
        List<SiteInfoEntity> siteInfoEntities = siteMapper.selectList(wrapper);
        log.info("获取网址列表 : size {}", siteInfoEntities.size());
        return buildPublicList(siteInfoEntities);
    }

    /**
     * 构造自定义ip
     *
     * @param dataList 站点列表
     */
    public List<SiteInfoEntity> buildPublicList(final List<SiteInfoEntity> dataList) {
        if (CollectionUtils.isEmpty(dataList)) {
            return dataList;
        }
        IpInfoEntity latest = ipInfoService.getLatestData(IPTypeEnum.REMOTE_HOME.getType(), null);
        if (Objects.isNull(latest)) {
            return dataList;
        }
        String prefix = SitePrefixEnum.CUSTOM_PREFIX.getValue();
        return dataList.stream()
                .peek(x -> {
                    String url = x.getUrl();
                    if (StringUtils.startsWith(url, prefix)) {
                        String ip = latest.getIpAddress();
                        String format = String.format(
                                SitePrefixEnum.CUSTOM_PREFIX.getTemplate(),
                                ip,
                                url.substring(2)
                        );
                        x.setUrl(format);
                    }
                })
                .collect(Collectors.toList());
    }

    /**
     * 分页获取数据列表
     *
     * @param params 查询参数
     * @return {@link SiteInfoEntity}
     */
    public Page<SiteInfoEntity> getList(final Map<String, Object> params) {
        final String title = (String) params.get("title");
        final LambdaQueryWrapper<SiteInfoEntity> wrapper = new LambdaQueryWrapper<SiteInfoEntity>()
                .like(StringUtils.isNotBlank(title), SiteInfoEntity::getTitle, title)
                .orderByDesc(SiteInfoEntity::getCreateTime);
        return siteMapper.selectPage(new Query<SiteInfoEntity>(params).getPage(), wrapper);
    }

    /**
     * excel导入
     */
    public String importData(final MultipartFile excel) {
        try (InputStream inputStream = excel.getInputStream()) {
            LoginUser user = UserUtils.getCurrentLoginUser();
            String msg = EasyExcelUtil.importData(
                    inputStream,
                    null,
                    SiteVO.class,
                    new Site35Listener(this, 10, user.getId())
            );
            log.info("importSite msg : {}", msg);
            return msg;
        } catch (IOException e) {
            log.error("获取excel输入流异常: ", e);
            return e.getLocalizedMessage();
        }
    }

    /**
     * 验证存在性
     *
     * @param title 名称
     * @return 是否存在 false 不存在 true 存在
     */
    public boolean verifyExist(final String title) {
        if (StringUtils.isBlank(title)) {
            throw new IllegalArgumentException("名称为空");
        }
        Long count = siteMapper.selectCount(new LambdaQueryWrapper<SiteInfoEntity>().eq(SiteInfoEntity::getTitle, title));
        return count > 0L;
    }

    /**
     * 逻辑删除
     *
     * @param ids 以逗号分割的id
     */
    public int delete(final String ids) {
        String[] split = ids.split(PunctuationConstants.SPLIT_COMMA);
        if (ArrayUtils.isEmpty(split)) {
            return 0;
        }
        LambdaUpdateWrapper<SiteInfoEntity> updateWrapper = new LambdaUpdateWrapper<SiteInfoEntity>()
                .set(SiteInfoEntity::getStatus, SiteEnum.DEL.getStatus())
                .in(SiteInfoEntity::getId, Arrays.asList(split));
        return siteMapper.update(updateWrapper);
    }
}
